」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > Go 和 Python 之間的 gRPC 通信

Go 和 Python 之間的 gRPC 通信

發佈於2024-11-08
瀏覽:537

gRPC Communication Between Go and Python

gRPC 是一个功能强大、高性能的远程过程调用 (RPC) 框架,尽管不如 REST 常用,但在某些场景中提供了显着的优势。

此外,它与语言无关,可以在任何环境中运行,使其成为服务器到服务器通信的理想选择。

我不会深入研究它的完整解释,但这里是 gRPC 的一般链接。我将提供实践教程

Go gRPC 客户端 

让我们想象一下,我们的 Go 是客户端,但对于前端应用程序 React、Svelte 等来说,它是服务器。

func getFirstArg() (string, error) {
    if len(os.Args) 



gRPC Communication Between Go and Python


作为示例,React 前端上传一个文件,Go 处理它,但我们需要来自 excel 的答案,我们将使用 GPT API。虽然可以用 Go 来完成,但另一方面 Python 有更多可以简化我们生活的软件包,例如 langchan_openai、pandas for excel 等等。


我们首先最好在您的 virtualenv .venv 中安装 gRPC

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
$ export PATH="$PATH:$(go env GOPATH)/bin"

接下来你应该在你的操作系统中安装protocol buffer,可以在此处安装。
让我们创建一个 proto 目录,您将在其中存储协议​​缓冲区文件,我将其命名为 excel.proto 并粘贴此:

syntax = "proto3";
option go_package = "client-gRPC/proto";
service ExcelService {
    rpc UploadFile(FileRequest) returns (FileResponse);
}
message FileRequest {
    string file_name = 1;
    bytes file_content = 2;
}
message FileResponse {
    bytes file_content = 1;
}

这个 gRPC 服务 ExcelService 允许客户端通过发送文件名称和内容来上传文件。服务器以相同的文件内容进行响应。 

对于 Go,在 Python 中传递 go_package 是必需的,不需要这一行。

如果您使用 VSCode,vscode-proto3 是一个很好的下载扩展。

完成所有这些之后,您可以生成原型文件,我更喜欢它与 prot 目录处于同一级别,为此运行此命令:

协议--go_out=。 --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/excel.proto

如果成功生成两个文件,如果需要进行大量调整,则可以选择添加一个 Makefile 并将其定义为 proto 上命令。

import (
    ....

    "google.golang.org/grpc"
    pb "client-gRPC/proto"
    "github.com/xuri/excelize/v2"
)

func main() {
    ....

    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("Failed to connect to gRPC server: %v", err)
    }
    defer conn.Close()

    client := pb.NewExcelServiceClient(conn)

    req := &pb.FileRequest{
        FileName:    filePath,
        FileContent: fileData,
    }

    res, err := client.UploadFile(context.Background(), req)
    if err != nil {
        log.Fatalf("Failed to upload file: %v", err)
    }

    outputFile := "output.xlsx"
    err = saveBytesAsExcel(outputFile, res.FileContent)
    if err != nil {
        log.Fatalf("Failed to save bytes as Excel file: %v", err)
    }

    fmt.Printf("Excel file saved as: %s\n", outputFile)
}

func saveBytesAsExcel(filePath string, fileContent []byte) error {
    f, err := excelize.OpenReader(bytes.NewReader(fileContent))
    if err != nil {
        return fmt.Errorf("failed to open Excel file: %v", err)
    }

    if err := f.SaveAs(filePath); err != nil {
        return fmt.Errorf("failed to save Excel file: %v", err)
    }
    return nil
}

我们建立一个连接来监听 50051,它将成为我们的 Python 服务器,&pb.FileRequest 是之前使用 proto 命令生成的,现在我们正在导入方法。如果你跑步你会收到?由于Python服务器尚未建立。

Failed to upload file: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 127.0.0.1:50051: connect: connection refused"

Python gRPC 服务器

由于 python 将充当服务器,因此方法会略有不同,但本质上不需要包字段中的相同原始文件。让我们首先创建一个不带 gRPC 的基础 main.py,以便了解 GPT 如何填充 excel 中的问题。

import os
import openai
import pandas as pd
from dotenv import load_dotenv

def get_answer_from_gpt(apikey: str, question: str):
    openai.api_key = apikey
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": question}
        ]
    )
    return response['choices'][0]['message']['content'].strip()

def answer_questions_df(df: pd.DataFrame, apikey: str):
    answers = []

    for question in df.iloc[:, 0]: 
        answer = get_answer_from_gpt(apikey, question)
        answers.append(answer)
    return answers

if __name__ == "__main__":
    load_dotenv()

    openai_api_key = os.getenv("OPENAI_API_KEY", "OpenAI API key hasn't been set.")

    df = pd.read_excel('Book1.xlsx')

    df['Answer'] = answer_questions_df(df, openai_api_key

这是一个简单的脚本,可以回答 Go 发送给我们的问题,但由于专用的 openai 库,LOC 较少,这使得它变得更容易。


我们首先添加具有与上面相同的文件的原始目录,可以按照讨论删除选项部分。最好在您的 virtualenv 中安装 gRPC,然后按照我运行的原型生成安装“

python3 -m grpc_tools.protoc --proto_path=proto --python_out=proto --grpc_python_out=proto proto/excel.proto

与我的原始目录处于相同的lvl 记得添加 __init.py

文件已生成,让我们继续。

import io
import grpc
from proto import excel_pb2_grpc as excel_grpc
from proto import excel_pb2

class ExcelService(excel_grpc.ExcelServiceServicer):
    def UploadFile(self, request, context):
        try:
            # Convert bytes to a file-like object
            file_like_object = io.BytesIO(request.file_content)

            # Load the workbook from the file-like object
            workbook = openpyxl.load_workbook(file_like_object)

            # Access the first sheet (or use appropriate logic to get the sheet you need)
            sheet = workbook.active

            # Convert the sheet to a DataFrame
            data = sheet.values
            columns = next(data)  # Get the header row
            df = pd.DataFrame(data, columns=columns)

            print("Loaded DataFrame:")
            print(df.head())

            # Ensure that the DataFrame is not empty and has questions
            if df.empty or df.shape[1] 



我们定义服务器并添加 ExcelService 类,其中包含 proto 文件生成的方法。因为我们按字节接收文件,所以必须使用 io 字节读取器并开始进一步处理文件并填充第二列。

response = excel_pb2.FileResponse(file_content=output.read())

最后我们返回 ☝️ 供 Go 客户端接收。

为了能够在 python 中找到原始文件,您应该定义一个导出路径

导出 PYTHONPATH=$PYTHONPATH:mnt/c/own_dev/gRPC/server/proto

运行客户端和服务器

If all is good you can run

#First comes server

python3 -m main

#Then client

go run client.go Book1.xlsx

您应该在 Go 客户端获得更新的 .xlsx 文件。

结论

在本文中,我们探讨了在 Python 服务器和 Go 客户端之间设置 gRPC 通信的基础知识。通过利用 gRPC,我们建立了一种无缝方式,将 Excel 文件从 Go 应用程序发送到 Python 服务器,使用 OpenAI 的 GPT API 处理文件,并将修改后的文件返回到 Go 客户端。

版本聲明 本文轉載於:https://dev.to/mozes721/grpc-communication-between-go-and-python-40i3?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何限制動態大小的父元素中元素的滾動範圍?
    如何限制動態大小的父元素中元素的滾動範圍?
    在交互式接口中實現垂直滾動元素的CSS高度限制問題:考慮一個佈局,其中我們具有與用戶垂直滾動一起移動的可滾動地圖div,同時與固定的固定sidebar保持一致。但是,地圖的滾動無限期擴展,超過了視口的高度,阻止用戶訪問頁面頁腳。 $("#map").css({ margin...
    程式設計 發佈於2025-04-06
  • 如何干淨地刪除匿名JavaScript事件處理程序?
    如何干淨地刪除匿名JavaScript事件處理程序?
    刪除匿名事件偵聽器將匿名事件偵聽器添加到元素中會提供靈活性和簡單性,但是當要刪除它們時,可以構成挑戰,而無需替換元素本身就可以替換一個問題。 element? element.addeventlistener(event,function(){/在這里工作/},false); 要解決此問題,請考...
    程式設計 發佈於2025-04-06
  • 如何在鼠標單擊時編程選擇DIV中的所有文本?
    如何在鼠標單擊時編程選擇DIV中的所有文本?
    在鼠標上選擇div文本單擊帶有文本內容,用戶如何使用單個鼠標單擊單擊div中的整個文本?這允許用戶輕鬆拖放所選的文本或直接複製它。 在單個鼠標上單擊的div元素中選擇文本,您可以使用以下Javascript函數: function selecttext(canduterid){ if(d...
    程式設計 發佈於2025-04-06
  • 如何將來自三個MySQL表的數據組合到新表中?
    如何將來自三個MySQL表的數據組合到新表中?
    mysql:從三個表和列的新表創建新表 答案:為了實現這一目標,您可以利用一個3-way Join。 選擇p。 *,d.content作為年齡 來自人為p的人 加入d.person_id = p.id上的d的詳細信息 加入T.Id = d.detail_id的分類法 其中t.taxonomy ...
    程式設計 發佈於2025-04-06
  • 如何同步迭代並從PHP中的兩個等級陣列打印值?
    如何同步迭代並從PHP中的兩個等級陣列打印值?
    同步的迭代和打印值來自相同大小的兩個數組使用兩個數組相等大小的selectbox時,一個包含country代碼的數組,另一個包含鄉村代碼,另一個包含其相應名稱的數組,可能會因不當提供了exply for for for the uncore for the forsion for for ytry...
    程式設計 發佈於2025-04-06
  • 為什麼PHP的DateTime :: Modify('+1個月')會產生意外的結果?
    為什麼PHP的DateTime :: Modify('+1個月')會產生意外的結果?
    使用php dateTime修改月份:發現預期的行為在使用PHP的DateTime類時,添加或減去幾個月可能並不總是會產生預期的結果。正如文檔所警告的那樣,“當心”這些操作的“不像看起來那樣直觀。 考慮文檔中給出的示例:這是內部發生的事情: 現在在3月3日添加另一個月,因為2月在2001年只有2...
    程式設計 發佈於2025-04-06
  • 如何使用PHP從XML文件中有效地檢索屬性值?
    如何使用PHP從XML文件中有效地檢索屬性值?
    從php PHP陷入困境。 使用simplexmlelement :: attributes()函數提供了簡單的解決方案。此函數可訪問對XML元素作為關聯數組的屬性: - > attributes()為$ attributeName => $ attributeValue){ echo...
    程式設計 發佈於2025-04-06
  • 如何使用Python理解有效地創建字典?
    如何使用Python理解有效地創建字典?
    在python中,詞典綜合提供了一種生成新詞典的簡潔方法。儘管它們與列表綜合相似,但存在一些顯著差異。 與問題所暗示的不同,您無法為鑰匙創建字典理解。您必須明確指定鍵和值。 For example:d = {n: n**2 for n in range(5)}This creates a dict...
    程式設計 發佈於2025-04-06
  • 對象擬合:IE和Edge中的封面失敗,如何修復?
    對象擬合:IE和Edge中的封面失敗,如何修復?
    To resolve this issue, we employ a clever CSS solution that solves the problem:position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%)...
    程式設計 發佈於2025-04-06
  • 可以在純CS中將多個粘性元素彼此堆疊在一起嗎?
    可以在純CS中將多個粘性元素彼此堆疊在一起嗎?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    程式設計 發佈於2025-04-06
  • Android如何向PHP服務器發送POST數據?
    Android如何向PHP服務器發送POST數據?
    在android apache httpclient(已棄用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    程式設計 發佈於2025-04-06
  • 如何有效地選擇熊貓數據框中的列?
    如何有效地選擇熊貓數據框中的列?
    在處理數據操作任務時,在Pandas DataFrames 中選擇列時,選擇特定列的必要條件是必要的。在Pandas中,選擇列的各種選項。 選項1:使用列名 如果已知列索引,請使用ILOC函數選擇它們。請注意,python索引基於零。 df1 = df.iloc [:,0:2]#使用索引0和1 ...
    程式設計 發佈於2025-04-06
  • 如何使用FormData()處理多個文件上傳?
    如何使用FormData()處理多個文件上傳?
    )處理多個文件輸入時,通常需要處理多個文件上傳時,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    程式設計 發佈於2025-04-06
  • 如何在GO編譯器中自定義編譯優化?
    如何在GO編譯器中自定義編譯優化?
    在GO編譯器中自定義編譯優化 GO中的默認編譯過程遵循特定的優化策略。 However, users may need to adjust these optimizations for specific requirements.Optimization Control in Go Compi...
    程式設計 發佈於2025-04-06
  • 為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    網格超過身體,用100%grid-template-columns 為什麼在grid-template-colms中具有100%的顯示器,當位置設置為設置的位置時,grid-template-colly修復了? 問題: 考慮以下CSS和html: class =“ snippet-code”> ...
    程式設計 發佈於2025-04-06

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3